package com.iwhalecloud.citybrain.flow.platform.manager.application.service.impl;

import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

import com.iwhalecloud.citybrain.flow.platform.manager.application.common.enums.UserEnum;
import com.iwhalecloud.citybrain.flow.platform.manager.application.service.FlowTenantService;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.model.FlowUser;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.model.User;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.model.app.FlowApp;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.model.tenant.FlowTenantSimpleInfoVo;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.model.tenant.FlowUserTenantAddVo;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.model.tenant.FlowUserTenantDeleteVo;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.model.tenant.FlowUserTenantSubmitVo;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.model.tenant.FlowUserTenantVo;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.repository.FlowAppRepository;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.repository.FlowTenantRepository;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.repository.FlowUserTenantRepository;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.repository.UserRepository;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * @author lilh
 * @date 2020/11/23 上午11:31
 */
@Service
public class FlowTenantServiceImpl implements FlowTenantService {

    @Autowired
    private FlowUserTenantRepository flowUserTenantRepository;

    @Autowired
    private UserRepository userRepository;

    @Autowired
    private FlowAppRepository flowAppRepository;

    @Autowired
    private FlowTenantRepository flowTenantRepository;

    @Override
    public List<FlowUserTenantVo> listUsersByTenantId(Integer tenantId) {
        if (Objects.isNull(tenantId)) {
            return Collections.emptyList();
        }
        return flowUserTenantRepository.listUsersByTenantId(tenantId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean addOrDelTenantUsers(FlowUserTenantSubmitVo flowUserTenantSubmitVo) {
        if (Objects.isNull(flowUserTenantSubmitVo.getTenantId())) {
            return false;
        }
        //对于新增的租户用户，需要往user表中增加记录,
        doAddTenantUsers(flowUserTenantSubmitVo);
        doDelTenantUsers(flowUserTenantSubmitVo);
        return true;
    }

    @Override
    public List<FlowApp> listAppByTenantAndUserCode(Integer tenantId, String userCode) {
        return flowAppRepository.listAppByTenantIdAndUserCode(tenantId, userCode);
    }

    @Override
    public List<FlowTenantSimpleInfoVo> listTenants(List<Integer> tenantIds) {
        return flowTenantRepository.listTenants(tenantIds);
    }

    private void doDelTenantUsers(FlowUserTenantSubmitVo flowUserTenantSubmitVo) {
        List<FlowUserTenantDeleteVo> delCols = flowUserTenantSubmitVo.getDelCol();
        if (CollectionUtils.isEmpty(delCols)) {
            return;
        }
        //1.根据userCode查询出待删除的用户信息
        List<User> existUsers = userRepository.listUserByUserCodes(delCols.stream().map(FlowUserTenantDeleteVo::getUserCode).collect(Collectors.toList()));
        Map<String, User> userCodeToUserMap = existUsers.stream().collect(Collectors.toMap(User::getUserCode, item -> item));

        for (FlowUserTenantDeleteVo deleteVo : delCols) {
            deleteVo.setTenantId(flowUserTenantSubmitVo.getTenantId());
            User exist = userCodeToUserMap.get(deleteVo.getUserCode());
            if (Objects.nonNull(exist) && isTenant(exist) && !hasAnotherTenant(exist, flowUserTenantSubmitVo.getTenantId())) {
                //若用户不再属于任何租户，则修改用户类型为normal
                updateUserType(exist, UserEnum.NORMAL.type());
            }
        }

        //删除租户-用户关系
        flowUserTenantRepository.delBatch(delCols, flowUserTenantSubmitVo.getTenantId());

        //删除应用-用户关系
        if (CollectionUtils.isNotEmpty(existUsers)) {
            flowAppRepository.authorizedCancel(existUsers.stream().map(User::getId).collect(Collectors.toList()), flowUserTenantSubmitVo.getTenantId());
        }


    }

    private boolean isTenant(User exist) {
        return Objects.equals(UserEnum.TENANT.type(), exist.getUserType());
    }

    private boolean hasAnotherTenant(User exist, Integer tenantId) {
        return flowUserTenantRepository.hasAnotherTenant(tenantId, exist.getUserCode());
    }

    private void doAddTenantUsers(FlowUserTenantSubmitVo flowUserTenantSubmitVo) {
        List<FlowUserTenantAddVo> addCols = flowUserTenantSubmitVo.getAddCol();
        if (CollectionUtils.isEmpty(addCols)) {
            return;
        }
        //1.根据userCode查询user表中用户信息
        List<User> existUsers = userRepository.listUserByUserCodes(addCols.stream().map(FlowUserTenantAddVo::getUserCode).collect(Collectors.toList()));
        Map<String, User> userCodeToUserMap = existUsers.stream().collect(Collectors.toMap(User::getUserCode, item -> item));

        //2.对已经存在的判断是否更新，不存在的则新增，类型为租户
        for (FlowUserTenantAddVo addVo : addCols) {
            addVo.setTenantId(flowUserTenantSubmitVo.getTenantId());
            User exist = userCodeToUserMap.get(addVo.getUserCode());
            if (Objects.nonNull(exist)) {
                //在user表中有记录,判断是否进行更新，若用户类型是normal，则更新
                if (Objects.equals(UserEnum.NORMAL.type(), exist.getUserType())) {
                    updateUserType(exist, UserEnum.TENANT.type());
                }
                addVo.setUserId(exist.getId());
            } else {
                //在user表中不存在，则新增
                addUser(addVo);
            }

        }

        //3.新增租户-用户关联记录
        flowUserTenantRepository.insertBatch(addCols);
    }

    private void addUser(FlowUserTenantAddVo addVo) {
        FlowUser flowUser = new FlowUser();
        flowUser.setUserCode(addVo.getUserCode());
        flowUser.setUserId(addVo.getUserCode());
        flowUser.setUserName(addVo.getUserName());
        flowUser.setUserType(UserEnum.TENANT.type());
        Integer count = userRepository.insertFlowUser(flowUser);
        if (count < 1) {
            throw new IllegalArgumentException("插入用户数据失败");
        }
        addVo.setUserId(flowUser.getId());
    }

    private void updateUserType(User exist, String userType) {
        FlowUser flowUser = new FlowUser();
        flowUser.setId(exist.getId());
        flowUser.setUserType(userType);
        userRepository.updateFlowUser(flowUser);
    }
}
